Skip to content

feat: OPENSHELL_DIRECT_TCP_ENDPOINTS for per-endpoint TCP bypass#1

Merged
kosaku-sim merged 1 commit intofix/sandbox-dns-udp-acceptfrom
direct-tcp-endpoints
Apr 21, 2026
Merged

feat: OPENSHELL_DIRECT_TCP_ENDPOINTS for per-endpoint TCP bypass#1
kosaku-sim merged 1 commit intofix/sandbox-dns-udp-acceptfrom
direct-tcp-endpoints

Conversation

@kosaku-sim
Copy link
Copy Markdown
Member

Summary

Adds a new env var OPENSHELL_DIRECT_TCP_ENDPOINTS (parallel to OPENSHELL_DIRECT_TCP_HOSTS) that accepts comma-separated host:port pairs, each installing per-endpoint iptables ACCEPT + MASQUERADE + FORWARD rules to bypass the egress proxy.

Motivation

The existing OPENSHELL_DIRECT_TCP_HOSTS installs a broad TCP 443 ACCEPT. This is sufficient for HTTPS services bypassing the proxy CA, but does not cover:

  • Non-HTTPS protocols the egress proxy cannot CONNECT-tunnel — postgres/redis wire protocols on access-full endpoints close with ECONNRESET
  • Ports the proxy explicitly blocks — observed: 5432, 6379, 15432, 16379 all return ECONNRESET even when listed in a host-private-ip policy block with access: full
  • Raw-TCP clients that ignore HTTP_PROXY env (e.g. pg, ioredis, smtp clients)

Use case: sandbox reaching postgres/redis/mailhog on the pod host (via AUTODEV_HOST_IP) without a port-forward daemon inside the sandbox.

Changes

  • netns.rs:
    • parse_direct_tcp_endpoints() — parse host:port pairs with validation
    • resolve_endpoint_ipv4s() — IPv4 literal or hostname resolution (IPv6 dropped)
    • Host-side POSTROUTING/FORWARD rules per (dest IP, dport)
    • Sandbox netns OUTPUT ACCEPT rule per (dest IP, dport), before the REJECT fast-fail
  • child_env.rs:
    • build_no_proxy() also includes host portion of each endpoint (so rustls/curl bypass proxy for those hosts too)
  • Unit tests for parsing edge cases and NO_PROXY integration

Verification

Built on Graviton (aarch64), binary deployed to the cluster container at /opt/openshell/bin/openshell-sandbox, sandbox CRD env set to:

OPENSHELL_DIRECT_TCP_ENDPOINTS=10.0.1.215:5432,10.0.1.215:6379,10.0.1.215:1025,10.0.1.215:8025

Pod recreated. Probe from inside the sandbox:

target before after
10.0.1.215:5432 (postgres) ECONNRESET ✅ connect + SELECT version() OK
10.0.1.215:6379 (redis) ECONNRESET ✅ connect
10.0.1.215:1025 (smtp) ECONNRESET ✅ connect
10.0.1.215:8025 (mailhog UI) ECONNRESET ✅ HTTP 200

Test plan

  • cargo test -p openshell-sandbox (unit tests for parsing + NO_PROXY)
  • runtime probe for all four endpoints
  • verified logi-go-api NestJS backend boots with Prisma pool + Redis client against host services

Adds a new env var parallel to OPENSHELL_DIRECT_TCP_HOSTS that accepts
host:port pairs (comma-separated). Each pair installs iptables rules:

- sandbox netns OUTPUT: ACCEPT to dest IP / dport
- host POSTROUTING: MASQUERADE for the same dest/port
- host FORWARD: ACCEPT for the same dest/port
- child_env NO_PROXY: host portion added so HTTP clients also bypass

Unlike DIRECT_TCP_HOSTS (broad TCP 443 ACCEPT), this is per-endpoint —
required for:
- non-HTTPS protocols the egress proxy cannot CONNECT-tunnel (postgres
  5432, redis 6379 wire protocols)
- ports the proxy explicitly blocks with ECONNRESET (5432, 6379, 15432,
  16379 observed)
- raw-TCP clients that ignore HTTP_PROXY env

Host component may be an IPv4 literal or hostname; hostnames are resolved
at pod startup via the pod netns resolver. IPv6 addresses are dropped
(sandbox iptables rules are IPv4-only).

Use case: sandbox reaching services on the pod host (postgres, redis,
mailhog) via AUTODEV_HOST_IP without a port-forward daemon inside the
sandbox.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@kosaku-sim kosaku-sim merged commit df4ca66 into fix/sandbox-dns-udp-accept Apr 21, 2026
5 of 10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant